#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##-- G09 -- S04 ------------------------------------------------------------##
__all__ = []

from .. import autostacks
from .. import formlib as layout
from .. import pilelib as stack
from .. import stackfill as fill
from ..gamelib import info as gi, state, game
from ..hint import CautiousDefaultHint
from ..packlib import info as cs, place

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class Foundation(stack.RK_Foundation):
    """
    Build up in rank alone. Rank _BOTTOM_IMAGE_ for cap['base_rank'] is ACE.
    """

    def getBottomImage(self):
        """
        getBottomImage() -> obj

        Show rank base image when base rank is ACE else show suit base.

        :return: base image
        :rtype: object
        """
        if self.cap['base_rank'] == cs.ACE:
            return self.game.images.base('rank', cs.ACE)
        return super(Foundation, self).getBottomImage()


class RowStack(stack.FromWasteBuildMethod, stack.ReserveStack):
    """
    Build any 1 card from _waste_. Play top.
    """
    pass


class RK_RowStack(stack.RK_RowStack):
    """
    Build down in rank alone. Shade _BOTTOM_IMAGE_.
    """
    _BOTTOM_IMAGE_ = 'shade'


class UD_RK_RowStack(stack.UD_RK_RowStack):
    """
    Build either in rank alone. Shade _BOTTOM_IMAGE_.
    """
    _BOTTOM_IMAGE_ = 'shade'


def makeCrossArms(l, x, y):
    """
    makeCrossArms(x:int, y:int) -> ITER

    iter a set of offsets to form a cross x by y with empty center.

    :param object l:layout.Layout object.
    :param integer x: x wide plus 1
    :param integer y: y high plus 1

    note:: size must be even numbers.
    """
    assert not bool(x % 2) or not bool(y % 2)
    dx, dy = x * 2 / 2, y * 2 / 2  # Arm size
    for d in (0, dx + 2):  # Left / Right
        for x in range(0, dx, 2):  # Horz
            yield (x + d) * l.XS / 2, dy * l.YS / 2
    for d in (0, dx + 2):  # Top / Bottom
        for y in range(0, dy, 2):  # Vert
            yield dx * l.XS / 2, (y + d) * l.YS / 2


def makeCrossCorners(l, x, y):
    """
    makeCrossCorners(x:int, y:int) -> ITER

    iter a set of offsets to place Pile 1 to each corner of cross.

    :param object l:layout.Layout object.
    :param integer x: x wide plus 1
    :param integer y: y high plus 1

    note:: size must be even numbers.
    """
    assert not bool(x % 2) or not bool(y % 2)
    dx, dy = x * 2 / 2, y * 2 / 2   # Arm size
    ddx, ddy = dx / 2 - 1, dy / 2 - 1  # Arm center
    dddx, dddy = ddx + dx + 2, ddy + dy + 2  # Arm step
    for d in (ddy, dddy):  # Left
        yield ddx * l.XS / 2, d * l.YS / 2
    for d in (ddy, dddy):  # Right
        yield dddx * l.XS / 2, d * l.YS / 2


class NapoleonsTomb(game.Game):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 4 cross arm. Init deal 1 card. Build 1 card from _waste_. Play top.

    _talon_
      Pile 1 NW. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 cross corner and 1 cross center. Build in rank alone:
      center down from base SIX wrap; corner up from base SEVEN. Play top.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: Foundation (base_rank=SIX, mod=13,
      max_cards=24, dir=-1), Foundation (base_rank=SEVEN, mod=13,
      max_cards=7)
    :cvar Stack _row_: RowStack
    """
    __info__ = dict(id=277, name='Napoleonʼs Tomb', game_type=(GT.ONE_DECK |
                    GT.KDE), decks=1, skill_level=SL.MOSTLY_LUCK,
                    version='0.80fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _waste_ = stack.WasteStack
    _foundations_ = (Wrap(Foundation, base_rank=cs.SIX, mod=13, max_cards=24,
                          dir=-1),
                     Wrap(Foundation, base_rank=cs.SEVEN, mod=13, max_cards=7),)
    _row_ = RowStack

    def _create_game(self, rows=(2, 2), **kw):
        l, s = layout.Layout(self), self.s
        f_rows = makeCrossCorners(l, *rows)
        r_rows = makeCrossArms(l, *rows)
        max_x = max(i[0] for i in f_rows + r_rows)
        max_y = max(i[1] for i in f_rows + r_rows)
        self.table_size = (2 * l.XS + max_x + l.XM, 1 * l.YS + max_y + l.YM)
        x, y = l.XM, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 's')
        x += l.XS
        s['wastes'].append(self._waste_(x, y, game=self))
        l.set_ncards_text(s['wastes'][-1], 's')
        dx, dy = x + l.XS, y
        for ddx, ddy in r_rows:  # Side
            s['rows'].append(self._row_(dx + ddx, dy + ddy, game=self,
                                     offset=(0, 0)))
        x, y = dx + (rows[0] / 2) * l.XS, dy + (rows[1] / 2) * l.YS
        s['foundations'].append(self._foundations_[0](x, y, game=self))  # Center
        for ddx, ddy in f_rows:  # Corner
            s['foundations'].append(self._foundations_[1](dx + ddx, dy + ddy,
                                                       game=self))
        l.defaultStackGroups()
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 1 ea.

        .. \_start([]) -> None
        """
        self.s['talon'].dealRow()


class DutchSolitaire(NapoleonsTomb):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 6 cross arm. Init deal 1 card. Build none. Play top.

    _talon_
      Pile 1 NW. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 cross corner and 1 cross center. Init deal base ACE heart center
      and Ace black corner. Build up in rank alone from base wrap. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: golf.stack.UD_RK_Foundation (suit=ANY, mod=13,
      max_cards=MAX, min_cards=1) * 2
    :cvar Stack _row_: UD_RK_RowStack
    """
    __info__ = dict(id=561, name='Dutch Solitaire', game_type=GT.TWO_DECK,
                    decks=2, skill_level=SL.MOSTLY_SKILL,
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _hint_ = CautiousDefaultHint
    _foundations_ = (Wrap(stack.UD_RK_Foundation, suit=cs.ANY, mod=13,
                          max_cards=cs.MAX, min_cards=1),) * 2
    _row_ = UD_RK_RowStack

    def _create_game(self, **kw):
        kw.setdefault('rows', (2, 4,))
        return super(DutchSolitaire, self)._create_game(**kw)

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return ACE club spade diamond on top by suit for
        _foundation_ deal.
        """
        return place.MoveToTop(cards, place.AceBlackDiamond)

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] base.
          - s[rows] 1 ea.

        .. \_start([]) -> None
        """
        self.s['talon'].dealBaseCards(ncards=len(self.s['foundations']),
                                      saveinfo=False)
        self.s['talon'].dealRow()

    @property
    def _highlight_piles(self):
        """
        Get stacks to highlight for possible move.

        :return: empty.
        :rtype: tuple
        """
        return ()


class Windmill(DutchSolitaire):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 8 cross arm. Init deal 1 card. Build 1 card from _waste_. Play top.
      Gap deal 1 card from _waste_.

    _talon_
      Pile 1 NW. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 cross corner and 1 cross center. Init deal base ACE center.
      Build up in rank alone: up from base wrap center; down from base
      KING corners. Play Top.

    note::
      ⟪highlight_play⟫, ⟪autodrop⟫, ⟪autoflip⟫, ⟪quickplay⟫ disabled
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: Foundation (mod=13, min_cards=1,
      max_cards=52), Foundation (base_rank=KING, dir=-1)
    :cvar Stack _row_: RowStack
    """
    __info__ = dict(id=30, name='Windmill', game_type=GT.TWO_DECK, decks=2,
                    skill_level=SL.MOSTLY_LUCK, version='2.90')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _foundations_ = (Wrap(Foundation, mod=13, min_cards=1, max_cards=52),
                     Wrap(Foundation, base_rank=cs.KING, dir=-1),)

    def _create_game(self, **kw):
        kw.setdefault('rows', (4, 4))
        return super(Windmill, self)._create_game(**kw)

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return single ACE on top for _foundation_ deal.
        """
        place.MoveToTop(cards, place.AllAce, ncards=1)

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base.
          - s[rows] 1 ea.

        .. \_start([]) -> None
        """
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self.s['talon'].dealRow()

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        Fill stack if _row_ when gap from _waste_.

        *Parameters*:
          stack : Stack
            pile just played
        """
        fill.fromWaste(self, stack, self.s['rows'])

    def _autopiles(self, event=None):
        """
        Return piles for auto or quick move.

        Overide to disable autoflip, autodrop, quickplay.

        .. \_autopiles(self, event=None) -> seq(seq(Pile ...), seq(Pile ...),
             seq(Pile ...))
        """
        return autostacks.none()


class FourSeasons(game.Game):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 4 cross arm. Init deal 1 card. Build none. Play top.

    _talon_
      Pile 1 NW. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 cross corner. Init deal 4 any base. Build up in rank alone from
      base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=1)
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0, mod=13)
    :cvar Stack _row_: RK_RowStack (mod=13, max_move=1)
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=484, name='Four Seasons', game_type=GT.ONE_DECK,
                    decks=1, skill_level=SL.MOSTLY_LUCK,
                    altnames=('Corner Card', 'Vanishing Cross',),
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _waste_ = stack.WasteStack
    _foundation_ = Wrap(stack.SS_Foundation, max_move=0, mod=13)
    _row_ = Wrap(RK_RowStack, mod=13, max_move=1)
    _hint_ = CautiousDefaultHint

    def _create_game(self, **kw):
        l, s = layout.Layout(self), self.s
        self.table_size = (5 * l.XS + l.XM, 4 * l.YS + 3 * l.YM)
        x, y = l.XM + 3 * l.XS / 2, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 'sw')
        l.set_rounds_text(self.s['talon'], 'nw')
        x += l.XS
        s['wastes'].append(self._waste_(x, y, game=self))
        l.set_ncards_text(s['wastes'][-1], 'se')
        dx, dy = l.XM, l.YM + l.YS
        for ddx, ddy, suit in zip(((0, 0,), (3, 0,), (0, 3,), (3, 3)),
                                  l.SUITS):
            x, y = dx + ddx * l.XS, dy + ddy * l.YS
            s['foundations'].append(self._foundation_(x, y, game=self,
                                                   suit=suit))
        for ddx, ddy in ((2, 0), (1, 1), (2, 1), (3, 1), (2, 2)):
            x, y = dx + ddx * l.XS, dy + ddy * l.YS
            s['rows'].append(self._row_(x, y, game=self, offset=(0, 0)))
        l.defaultStackGroups()
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base. save all caps.
          - s[rows] 1 ea.

        .. \_start([]) -> None
        """
        base_rank = self.s['talon'].TOPCARD['rank']
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self._save_stack_caps(self.s['foundations'], base_rank=base_rank)
        self.s['talon'].dealRow()


class Czarina(FourSeasons):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 4 cross arm. Init deal 1 card. Build none. Play top. Gap deal 1
      card from _waste_.

    _talon_
      Pile 1 NW. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 cross corner. Init deal 4 any base. Build up in rank alone from
      base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=1)
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0, mod=13)
    :cvar Stack _row_: RK_RowStack (mod=13, max_move=1)
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=483, name='Czarina', game_type=GT.ONE_DECK, decks=1,
                    skill_level=SL.MOSTLY_LUCK, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        Fill stack if _row_ when gap from _waste_.

        *Parameters*:
           stack : Stack
             pile just played
        """
        fill.fromWaste(self, stack, self.s['rows'])


class Corners(Czarina):
    """
    Finish cards on _foundation_ within 3 turns.

    _row_
      Pile 4 cross arm. Init deal 1 card. Build none. Play top. Gap deal 1
      card from _waste_.

    _talon_
      Pile 1 NW. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 cross corner. Init deal 4 suit base. Build up in rank alone from
      base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=3)
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0, mod=13)
    :cvar Stack _row_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=417, name='Corners', game_type=GT.ONE_DECK, decks=1,
                    redeals=2, skill_level=SL.MOSTLY_LUCK, version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=3)
    _row_ = stack.ReserveStack

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to any rank of suit on top by suit, deck for _foundation_ deal.
        """
        return place.MoveToTop(cards, ncards=4)

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] base.
          - s[rows] 1 ea.

        .. \_start([]) -> None
        """
        self.s['talon'].dealBaseCards(ncards=len(self.s['foundations']),
                                      saveinfo=False)
        self.s['talon'].dealRow()


class FlorentinePatience(FourSeasons):
    """
    Finish cards on _foundation_ within 2 turns.

    _row_
      Pile 4 cross arm. Init deal 1 card. Build none. Play top.

    _talon_
      Pile 1 NW. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 cross corner. Init deal 4 any base. Build up in rank alone from
      base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=2)
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0, mod=13)
    :cvar Stack _row_: RK_RowStack (mod=13, max_move=1)
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=696, name='Florentine Patience', game_type=GT.ONE_DECK,
                    decks=1, redeals=1, skill_level=SL.MOSTLY_LUCK,
                    version='1.00fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=2)


class Simplicity(game.Game):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 12 over 2 row. Init deal 1 card. Build none. Play top.

    _talon_
      Pile 1 N. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      4 pile cross corner. Init deal 1 base card. Build up in rank alone from
      base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: stack.AC_RowStack (mod=13, max_move=1)
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=437, name='Simplicity', game_type=GT.ONE_DECK, decks=1,
                    skill_level=SL.MOSTLY_LUCK, version='1.00fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _waste_ = stack.WasteStack
    _foundation_ = Wrap(stack.Vary_SS_Foundation, max_move=0)
    _row_ = Wrap(stack.AC_RowStack, max_move=1, mod=13)
    _hint_ = CautiousDefaultHint

    def _create_game(self, **kw):
        l, s = layout.Layout(self), self.s
        self.table_size = (l.XM + 8 * l.XS, l.YM + 4 * l.YS)
        dx, dy = l.XM, l.YM
        for ddx, ddy, suit in zip(((0, 7, 0, 7), (0, 0, 3, 3)), l.SUITS):
            x, y = dx + ddx * l.XS, dy + ddy * l.YS
            s['foundations'].append(self._foundation_(x, y, game=self,
                                                   suit=suit))
        dx = l.XM + l.XS
        y += l.YS
        for row in (6,) * 2:
            x = dx
            for i in range(row):
                s['rows'].append(self._row_(x, y, game=self, offset=(0, 0)))
                x += l.XS
            y += l.YS
        x, y = l.XM + 3 * l.XS, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 'sw')
        x += l.XS
        s['wastes'].append(self._waste_(x, y, game=self))
        l.set_ncards_text(s['wastes'][-1], 'se')
        l.defaultStackGroups()
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base. save all caps
          - s[rows] 1 ea.

        .. \_start([]) -> None
        """
        base_rank = self.s['talon'].TOPCARD['rank']
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self._save_stack_caps(self.s['foundations'], base_rank=base_rank)
        self.s['talon'].dealRow()


class RoyalEast(game.Game):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 5 cross arm. Init deal 1 card. Build down in rank alone wrap. Play
      top.

    _talon_
      Pile 1 W. Deal _waste 1 card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 cross corner. Init deal base card. Build down in rank by same
      suit from base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: stack.RK_RowStack (mod=13, max_move=1)
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=93, name='Royal East', game_type=(GT.ONE_DECK |
                    GT.GNOME), decks=1, skill_level=SL.BALANCED,
                    version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _waste_ = stack.WasteStack
    _foundation_ = Wrap(stack.Vary_SS_Foundation, max_move=0)
    _row_ = Wrap(stack.RK_RowStack, mod=13, max_move=1)
    _hint_ = CautiousDefaultHint

    def _create_game(self):
        l, s = layout.Layout(self), self.s
        self.table_size = (l.XM + 11 * l.XS / 2, l.YM + 4 * l.YS)
        ddx, ddy = l.XM + 5 * l.XS / 2, l.YM + l.YS / 2
        for i, (dx, dy) in zip(l.SUITS, ((0, 0), (2, 0), (0, 2), (2, 2),)):
            x, y = l.delta_coords(x=ddx, y=ddy, dx=dx, dy=dy)
            s['foundations'].append(self._foundation_(x, y, game=self, suit=i))
        for dx, dy in ((2, 0), (0, 2), (2, 2), (4, 2), (2, 4),):
            x, y = l.delta_coords(x=ddx, y=ddy, dx=dx, dy=dy)
            s['rows'].append(self._row_(x, y, game=self, offset=(0, 0)))
        x, y = l.XM, l.YM + 3 * l.YS / 2
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 's')
        x += l.XS
        s['wastes'].append(self._waste_(x, y, self))
        l.set_ncards_text(s['wastes'][-1], 's')
        l.defaultStackGroups()
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base. save all caps
          - s[rows] 1 ea.

        .. \_start([rows:int=3, flip=True]) -> None
        """
        base_rank = self.s['talon'].TOPCARD['rank']
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self._save_stack_caps(self.s['foundations'], base_rank=base_rank)
        self.s['talon'].dealRow()


PROVIDES = [Windmill, NapoleonsTomb, Corners, Simplicity, Czarina,
            FourSeasons, DutchSolitaire, FlorentinePatience, RoyalEast]